package edu.hawaii.halealohacli.command;

import java.util.Formatter;
import java.util.Locale;
import javax.xml.datatype.XMLGregorianCalendar;
import org.wattdepot.client.BadXmlException;
import org.wattdepot.client.MiscClientException;
import org.wattdepot.client.NotAuthorizedException;
import org.wattdepot.client.ResourceNotFoundException;
import org.wattdepot.client.WattDepotClient;
import org.wattdepot.util.tstamp.Tstamp;

/**
 * Returns the energy in kWh used by the tower or lounge for the specified date (yyyy-mm-dd).
 * 
 * @author Sergey Negrashov
 */
public class DailyEnergy implements Command {

  /**
   * Name of this module.
   */
  static final String MODULE_NAME = "daily-energy";

  /**
   * Usage for this module.
   */
  static final String MODULE_USAGE = MODULE_NAME
      + ": [tower | lounge] [Date]\nReturns the energy in kWh used by the tower or lounge for"
      + " the specified date (yyyy-mm-dd).\n\n";

  /**
   * First argument as passed to the module.
   */
  String sourceName;

  /**
   * Start time.
   */
  XMLGregorianCalendar startDate;

  /**
   * A flag to check if the arguments and client are ok.
   */
  boolean ok;

  /**
   * Error string.
   */
  String error = "Unknown error";

  /**
   * Client to use with this command.
   */
  WattDepotClient client;

  @Override
  public void initialize(String[] args, WattDepotClient client) {
    ok = true;
    this.client = client;
    if (args.length != 2) {
      error = "Not enough arguments.";
      ok = false;
      return;
    }
    sourceName = args[0];
    try {
      this.startDate = Tstamp.makeTimestamp(args[1]);
    }
    catch (Exception e) {
      ok = false;
      error = "Argument \"" + args[1] + "\" is invalid :" + e.getMessage();
      return;
    }
    //startDate = Tstamp.incrementMinutes(startDate, -10);
    startDate.setHour(0);
    startDate.setMinute(0);
    startDate.setSecond(0);
    startDate.setMillisecond(0);
    XMLGregorianCalendar today = Tstamp.makeTimestamp();
    if (Tstamp.greaterThan(startDate, today)) {
      ok = false;
      error = "The start date cannot be in the future.";
      return;
    }
  }

  @Override
  public void execute() {
    if (!ok) {
      System.out.println(error);
      return;
    }
    if (!client.isHealthy()) {
      System.out.println("Could not connect to the server.");
      return;
    }
    try {
      if (client.getSource(sourceName) != null) {
        System.out.println(printDailyEnergy());
      }
    }
    catch (NotAuthorizedException e) {
      System.out.println("Not authorized to view source " + sourceName);
      return;
    }
    catch (ResourceNotFoundException e) {
      System.out.println("No such source " + sourceName);
      return;
    }
    catch (BadXmlException e) {
      System.out.println("Bad xml " + e.getMessage());
      return;
    }
    catch (MiscClientException e) {
      System.out.println("Unknown Error " + e.getMessage());
      return;
    }

  }

  @Override
  public String getCommandName() {
    return MODULE_NAME;
  }

  @Override
  public String getCommandUsage() {
    return MODULE_USAGE;
  }

  /**
   * Computes the energy consumed from the given day and a given sensor.
   * 
   * @return formated string with the power used.
   * @throws NotAuthorizedException <code>execute</code> handles the exceptions and error checking.
   * @throws ResourceNotFoundException <code>execute</code> handles the exceptions and error
   * checking.
   * @throws BadXmlException <code>execute</code> handles the exceptions and error checking.
   * @throws MiscClientException <code>execute</code> handles the exceptions and error checking.
   */
  public String printDailyEnergy() throws NotAuthorizedException, ResourceNotFoundException,
      BadXmlException, MiscClientException {
    StringBuilder sb = new StringBuilder();
    Formatter formatter = new Formatter(sb, Locale.US);
    if (!ok) {
      return formatter.toString();
    }
    XMLGregorianCalendar endDate = Tstamp.incrementDays(startDate, 1);
    XMLGregorianCalendar today = Tstamp.incrementMinutes(Tstamp.makeTimestamp(), -5);
    if (Tstamp.greaterThan(endDate, today)) {
      endDate = Tstamp.incrementMinutes(today, -5);
    }
    Double energySince = 0.0;
    energySince = client.getEnergyConsumed(sourceName, startDate, endDate, 15);
    formatter.format("%1$s's energy consumption for %2$tF was: %3$.1f kWh", sourceName,
        startDate.toGregorianCalendar(), energySince / 1000);
    return formatter.toString();
  }

}
